using MyStateMathine;
using MyTimer;
using Services;
using UnityEngine;

[RequireComponent(typeof(SpriteRenderer))]
public class WaterReflection : MonoBehaviour
{
    private GlobalGameCycle gameCycle;
    private Camera mainCamera;
    private CameraController cameraController;
    private Transform transform_camera;

    private SpriteRenderer spriteRenderer_character;
    private SpriteRenderer spriteRenderer;

    private Rect cullRect;

    private bool Active
    {
        set
        {
            spriteRenderer.enabled = value;
            if (value)
            {
                float ratio = MirrorSimulateTool.CalculateReflectionRelativeLength(spriteRenderer_character.transform.position, mainCamera);
                Vector3 localScale = transform.localScale;
                transform.localScale = new Vector3(localScale.x, spriteRenderer_character.transform.localScale.y * ratio, localScale.z);
                transform.localPosition = new Vector2(0, -0.5f - ratio / 2);
            }
        }
    }

    private void Awake()
    {
        gameCycle = ServiceLocator.Get<GlobalGameCycle>();
        SpriteRenderer[] renderers = GetComponentsInParent<SpriteRenderer>();
        spriteRenderer = renderers[0];
        spriteRenderer_character = renderers[1];

        EventSystem eventSystem = ServiceLocator.Get<EventSystem>();
        eventSystem.AddListener(EEvent.CameraSizeChange, UpdateCullRect);
        eventSystem.AddListener<int>(EEvent.AfterLoadScene, Enable);
        eventSystem.AddListener<int>(EEvent.BeforeLoadScene, Disable);
    }

    private void Update()
    {
        spriteRenderer.sprite = spriteRenderer_character.sprite;
    }

    private void UpdateActive()
    {
        Active = cullRect.Contains(transform.position - transform_camera.position);
    }


    private void UpdateCullRect()
    {
        Sprite sprite = spriteRenderer_character.sprite;
        float width = sprite.rect.width / sprite.pixelsPerUnit;
        float height = sprite.rect.height / sprite.pixelsPerUnit;    
        cullRect = cameraController.GetRect(width, width, height, height + height * MirrorSimulateTool.MaxLength);
    }

    private void Enable(int _)
    {
        if (SceneController.InGame)
        {
            spriteRenderer.color = Color.white;
            mainCamera = Camera.main;
            cameraController = mainCamera.GetComponent<CameraController>();
            transform_camera = mainCamera.transform;
            UpdateCullRect();
            gameCycle.AttachToGameCycle(EInvokeMode.LateUpdate, UpdateActive);
        }
        else
        {
            spriteRenderer.color = Color.clear;
        }
    }

    private void Disable(int _)
    {
        if (SceneController.InGame)
        {
            gameCycle.RemoveFromGameCycle(EInvokeMode.LateUpdate, UpdateActive);
        }
    }
}
